/*
Copyright IT People Corp. 2017 All Rights Reserved.

SPDX-License-Identifier: Apache-2.0

*/

///////////////////////////////////////////////////////////////////////
// Author : IT People - Mohan Venkataraman - Auction API for v1.0
// Purpose: Explore the Hyperledger/fabric and understand
// how to write an chain code, application/chain code boundaries
// The code is not the best as it has just hammered out in a day or two
// Feedback and updates are appreciated
///////////////////////////////////////////////////////////////////////

package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"os"
	"runtime"
	"strconv"
	"time"

	"github.com/hyperledger/fabric/core/chaincode/shim"
	pb "github.com/hyperledger/fabric/protos/peer"
)

///////////////////////////////////////////////////////////////////////////////////////
// This creates a record of the Asset (Inventory)
// Includes Description, title, certificate of authenticity or image whatever..idea is to checkin a image and store it
// in encrypted form
// Example:
// Item { 113869, "Flower Urn on a Patio", "Liz Jardine", "10102007", "Original", "Floral", "Acrylic", "15 x 15 in", "sample_9.png","$600", "My Gallery }
///////////////////////////////////////////////////////////////////////////////////////

type ItemObject struct {
	ItemID         string
	RecType        string
	ItemDesc       string
	ItemDetail     string // Could included details such as who created the Art work if item is a Painting
	ItemDate       string
	ItemType       string
	ItemSubject    string
	ItemMedia      string
	ItemSize       string
	ItemPicFN      string
	ItemImage      []byte // This has to be generated AES encrypted using the file name
	AES_Key        []byte // This is generated by the AES Algorithms
	ItemImageType  string // should be used to regenerate the appropriate image type
	ItemBasePrice  string // Reserve Price at Auction must be greater than this price
	CurrentOwnerID string // This is validated for a user registered record
	TimeStamp      string // This is the time stamp
}

////////////////////////////////////////////////////////////////////////////////
// Has an item entry every time the item changes hands
////////////////////////////////////////////////////////////////////////////////
type ItemLog struct {
	ItemID       string // PRIMARY KEY
	Status       string // SECONDARY KEY - OnAuc, OnSale, NA
	AuctionedBy  string // SECONDARY KEY - Auction House ID if applicable
	RecType      string // ITEMHIS
	ItemDesc     string
	CurrentOwner string
	Date         string // Date when status changed
}

/////////////////////////////////////////////////////////////
// Create Buyer, Seller , Auction House, Authenticator
// Could establish valid UserTypes -
// AH (Auction House)
// TR (Buyer or Seller)
// AP (Appraiser)
// IN (Insurance)
// BK (bank)
// SH (Shipper)
/////////////////////////////////////////////////////////////
type UserObject struct {
	UserID    string
	RecType   string // Type = USER
	Name      string
	UserType  string // Auction House (AH), Bank (BK), Buyer or Seller (TR), Shipper (SH), Appraiser (AP)
	Address   string
	Phone     string
	Email     string
	Bank      string
	AccountNo string
	RoutingNo string
	Timestamp string
}

/////////////////////////////////////////////////////////////////////////////
// Register a request for participating in an auction
// Usually posted by a seller who owns a piece of ITEM
// The Auction house will determine when to open the item for Auction
// The Auction House may conduct an appraisal and genuineness of the item
/////////////////////////////////////////////////////////////////////////////

type AuctionRequest struct {
	AuctionID      string
	RecType        string // AUCREQ
	ItemID         string
	AuctionHouseID string // ID of the Auction House managing the auction
	SellerID       string // ID Of Seller - to verified against the Item CurrentOwnerId
	RequestDate    string // Date on which Auction Request was filed
	ReservePrice   string // reserver price > previous purchase price
	BuyItNowPrice  string // 0 (Zero) if not applicable else specify price
	Status         string // INIT, OPEN, CLOSED (To be Updated by Trgger Auction)
	OpenDate       string // Date on which auction will occur (To be Updated by Trigger Auction)
	CloseDate      string // Date and time when Auction will close (To be Updated by Trigger Auction)
	TimeStamp      string // The transaction Date and Time
}

/////////////////////////////////////////////////////////////
// POST the transaction after the Auction Completes
// Post an Auction Transaction
// Post an Updated Item Object
// Once an auction request is opened for auctions, a timer is kicked
// off and bids are accepted. When the timer expires, the highest bid
// is selected and converted into a Transaction
// This transaction is a simple view
/////////////////////////////////////////////////////////////

type ItemTransaction struct {
	AuctionID   string
	RecType     string // POSTTRAN
	ItemID      string
	TransType   string // Sale, Buy, Commission
	UserId      string // Buyer or Seller ID
	TransDate   string // Date of Settlement (Buyer or Seller)
	HammerTime  string // Time of hammer strike - SOLD
	HammerPrice string // Total Settlement price
	Details     string // Details about the Transaction
}

////////////////////////////////////////////////////////////////
//  This is a Bid. Bids are accepted only if an auction is OPEN
////////////////////////////////////////////////////////////////

type Bid struct {
	AuctionID string
	RecType   string // BID
	BidNo     string
	ItemID    string
	BuyerID   string // ID Of Buyer - to be verified against the Item CurrentOwnerId
	BidPrice  string // BidPrice > Previous Bid
	BidTime   string // Time the bid was received
}

//////////////////////////////////////////////////////////////
// Invoke Functions based on Function name
// The function name gets resolved to one of the following calls
// during an invoke
//
//////////////////////////////////////////////////////////////
func InvokeFunction(fname string) func(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {
	InvokeFunc := map[string]func(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response{
		"iPostItem":           PostItem,
		"iPostUser":           PostUser,
		"iPostAuctionRequest": PostAuctionRequest,
		"iPostTransaction":    PostTransaction,
		"iPostBid":            PostBid,
		"iOpenAuctionForBids": OpenAuctionForBids,
		"iBuyItNow":           BuyItNow,
		"iTransferItem":       TransferItem,
		"iCloseAuction":       CloseAuction,
		"iCloseOpenAuctions":  CloseOpenAuctions,
		"iDownloadImages":     DownloadImages,
	}
	return InvokeFunc[fname]
}

//////////////////////////////////////////////////////////////
// Query Functions based on Function name
//
//////////////////////////////////////////////////////////////
func QueryFunction(fname string) func(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {
	QueryFunc := map[string]func(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response{
		"qGetItem":               GetItem,
		"qGetUser":               GetUser,
		"qGetAuctionRequest":     GetAuctionRequest,
		"qGetTransaction":        GetTransaction,
		"qGetBid":                GetBid,
		"qGetLastBid":            GetLastBid,
		"qGetHighestBid":         GetHighestBid,
		"qGetNoOfBidsReceived":   GetNoOfBidsReceived,
		"qGetListOfBids":         GetListOfBids,
		"qGetItemLog":            GetItemLog,
		"qGetItemListByCat":      GetItemListByCat,
		"qGetUserListByCat":      GetUserListByCat,
		"qGetListOfInitAucs":     GetListOfInitAucs,
		"qGetListOfOpenAucs":     GetListOfOpenAucs,
		"qValidateItemOwnership": ValidateItemOwnership,
	}
	return QueryFunc[fname]
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
// We are storing the PictureMap as a Key/Value pair to download the images on the container.
// This was done to run the Daily/Weeky Test Cases from CLI
/////////////////////////////////////////////////////////////////////////////////////////////////////

//func GetPictureUrl(picname string) string {
var PictureMap = map[string]string{
	"art1.png":     "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art1.png",
	"art2.png":     "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art2.png",
	"art3.png":     "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art3.png",
	"art4.png":     "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art4.png",
	"art5.png":     "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art5.png",
	"art6.png":     "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art6.png",
	"art7.png":     "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art7.png",
	"item-001.jpg": "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-001.jpg",
	"item-002.jpg": "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-002.jpg",
	"item-003.jpg": "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-003.jpg",
	"item-004.jpg": "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-004.jpg",
	"item-005.jpg": "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-005.jpg",
	"item-006.jpg": "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-006.jpg",
	"item-007.jpg": "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-007.jpg",
	"item-008.jpg": "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-008.jpg",
	"people.gif":   "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/people.gif",
	"mad-fb.jpg":   "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/mad-fb.gif",
	"sample.png":   "https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/sample.png",
}

type SimpleChaincode struct {
}

////////////////////////////////////////////////////////////////////////////////
// Chain Code Kick-off Main function
////////////////////////////////////////////////////////////////////////////////
func main() {

	// maximize CPU usage for maximum performance
	runtime.GOMAXPROCS(runtime.NumCPU())
	fmt.Println("Starting Item Auction Application chaincode BlueMix ver 21 Dated 2016-07-02 09.45.00: ")

	//ccPath = fmt.Sprintf("%s/src/github.com/hyperledger/fabric/auction/art/artchaincode/", gopath)
	// Start the shim -- running the fabric
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Println("Error starting Item Fun Application chaincode: %s", err)
	}

}

/////////////////////////////////////////////////////////////////////////////////////////////////////
// We are storing the PictureMap as a Key/Value pair to download the images on the container.
// This was done to run the Daily/Weeky Test Cases from CLI
/////////////////////////////////////////////////////////////////////////////////////////////////////

func downloadFile(filepath string, url string) (err error) {

	// Create the file
	out, err := os.Create(filepath)
	if err != nil {
		return err
	}
	defer out.Close()

	// Get the data
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// Writer the body to file
	_, err = io.Copy(out, resp.Body)
	if err != nil {
		return err
	}

	return nil
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SimpleChaincode - Init Chaincode implementation - The following sequence of transactions can be used to test the Chaincode
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {

	// TODO - Include all initialization to be complete before Invoke and Query
	// Uses aucTables to delete tables if they exist and re-create them

	//myLogger.Info("[Trade and Auction Application] Init")
	fmt.Println("[Trade and Auction Application] Init")
	fmt.Println("\nInit() Initialization Complete ")
	return shim.Success(nil)
}

////////////////////////////////////////////////////////////////
// SimpleChaincode - INVOKE Chaincode implementation
// User Can Invoke
// - Register a user using PostUser
// - Register an item using PostItem
// - The Owner of the item (User) can request that the item be put on auction using PostAuctionRequest
// - The Auction House can request that the auction request be Opened for bids using OpenAuctionForBids
// - One the auction is OPEN, registered buyers (Buyers) can send in bids vis PostBid
// - No bid is accepted when the status of the auction request is INIT or CLOSED
// - Either manually or by OpenAuctionRequest, the auction can be closed using CloseAuction
// - The CloseAuction creates a transaction and invokes PostTransaction
////////////////////////////////////////////////////////////////

func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {

	function, args := stub.GetFunctionAndParameters()
	fmt.Println("==========================================================")
	fmt.Println("BEGIN Function ====> ", function)
	if function[0:1] == "i" {
		fmt.Println("==========================================================")
		return t.invoke(stub, function, args)
	}

	if function[0:1] == "q" {
		fmt.Println("==========================================================")
		return t.query(stub, function, args)
	}

	fmt.Println("==========================================================")

	return shim.Error("Invoke: Invalid Function Name - function names begin with a q or i")

}

////////////////////////////////////////////////////////////////
// SimpleChaincode - INVOKE Chaincode implementation
// User Can Invoke
// - Register a user using PostUser
// - Register an item using PostItem
// - The Owner of the item (User) can request that the item be put on auction using PostAuctionRequest
// - The Auction House can request that the auction request be Opened for bids using OpenAuctionForBids
// - One the auction is OPEN, registered buyers (Buyers) can send in bids vis PostBid
// - No bid is accepted when the status of the auction request is INIT or CLOSED
// - Either manually or by OpenAuctionRequest, the auction can be closed using CloseAuction
// - The CloseAuction creates a transaction and invokes PostTransaction
////////////////////////////////////////////////////////////////

func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// Check Type of Transaction and apply business rules
	// before adding record to the block chain
	// In this version, the assumption is that args[1] specifies recType for all defined structs
	// Newer structs - the recType can be positioned anywhere and ChkReqType will check for recType
	// example:
	// ./peer chaincode invoke -l golang -n mycc -c '{"Function": "PostBid", "Args":["1111", "BID", "1", "1000", "300", "1200"]}'
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	if ChkRecType(args) == true {

		InvokeRequest := InvokeFunction(function)
		if InvokeRequest != nil {
			response := InvokeRequest(stub, function, args)
			return (response)
		}
	} else {
		fmt.Println("Invoke() Invalid recType : ", args, "\n")
		error_str := "Invoke() : Invalid recType : " + args[0]
		return shim.Error(error_str)
	}

	return shim.Success(nil)
}

//////////////////////////////////////////////////////////////////////////////////////////
// SimpleChaincode - query Chaincode implementation
// Client Can Query
// Sample Data
// ./peer chaincode query -l golang -n mycc -c '{"Function": "GetUser", "Args": ["4000"]}'
// ./peer chaincode query -l golang -n mycc -c '{"Function": "GetItem", "Args": ["2000"]}'
//////////////////////////////////////////////////////////////////////////////////////////

func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	// var buff []byte
	var response pb.Response
	fmt.Println("Query() : ID Extracted and Type = ", args[0])
	fmt.Println("Query() : Args supplied : ", args)

	if len(args) < 1 {
		fmt.Println("Query() : Include at least 1 arguments Key ")
		return shim.Error("Query() : Expecting Transaction type and Key value for query")
	}

	QueryRequest := QueryFunction(function)
	if QueryRequest != nil {
		response = QueryRequest(stub, function, args)
	} else {
		fmt.Println("Query() Invalid function call : ", function)
		response_str := "Query() : Invalid function call : " + function
		return shim.Error(response_str)
	}

	if response.Status != shim.OK {
		fmt.Println("Query() Object not found : ", args[0])
		response_str := "Query() : Object not found : " + args[0]
		return shim.Error(response_str)
	}
	return response
}

//////////////////////////////////////////////////////////////////////////////////////////
// Download Images into Peer
//////////////////////////////////////////////////////////////////////////////////////////
func DownloadImages(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	fmt.Println("[Trade and Auction Application] DownloadImages")
	var err error
	for k, v := range PictureMap {
		fmt.Printf("\n Downloading Image '%s' from URL:  %s", k, v)
		err = downloadFile(k, v)
		if err != nil {
			fmt.Println(err)
			return shim.Error("Invoke: Invalid Function Name - function names begin with a q or i")
		}
	}
	fmt.Println("\nDownloadImages() Complete ")
	return shim.Success(nil)
}

//////////////////////////////////////////////////////////////////////////////////////////
// Retrieve User Information
// example:
// ./peer chaincode query -l golang -n mycc -c '{"Function": "GetUser", "Args": ["100"]}'
//
//////////////////////////////////////////////////////////////////////////////////////////
func GetUser(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	var err error

	// Get the Object and Display it
	Avalbytes, err := QueryObject(stub, "User", args)
	if err != nil {
		fmt.Println("GetUser() : Failed to Query Object ")
		jsonResp := "{\"Error\":\"Failed to get  Object Data for " + args[0] + "\"}"
		return shim.Error(jsonResp)
	}

	if Avalbytes == nil {
		fmt.Println("GetUser() : Incomplete Query Object ")
		jsonResp := "{\"Error\":\"Incomplete information about the key for " + args[0] + "\"}"
		return shim.Error(jsonResp)
	}

	fmt.Println("GetUser() : Response : Successful -")
	return shim.Success(Avalbytes)
}

/////////////////////////////////////////////////////////////////////////////////////////
// Query callback representing the query of a chaincode
// Retrieve a Item by Item ID
// QueryObjectWithProcessingFunction takes a post processing function as argument
// peer chaincode query -l golang -n mycc -c '{"Args": ["qGetItem", "1000"]}
//
/////////////////////////////////////////////////////////////////////////////////////////
func GetItem(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	var err error

	// Get the Objects and Display it
	Avalbytes, err := QueryObjectWithProcessingFunction(stub, "Item", args, ProcessQueryResult)
	if err != nil {
		fmt.Println("GetItem() : Failed to Query Object ")
		jsonResp := "{\"Error\":\"Failed to get  Object Data for " + args[0] + "\"}"
		return shim.Error(jsonResp)
	}

	if Avalbytes == nil {
		fmt.Println("GetItem() : Incomplete Query Object ")
		jsonResp := "{\"Error\":\"Incomplete information about the key for " + args[0] + "\"}"
		return shim.Error(jsonResp)
	}

	// Masking ItemImage binary data
	itemObj, _ := JSONtoAR(Avalbytes)
	itemObj.ItemImage = []byte{}
	Avalbytes, _ = ARtoJSON(itemObj)

	fmt.Println("GetItem() : Response : Successful ")
	return shim.Success(Avalbytes)
}

/////////////////////////////////////////////////////////////////////////////////////////
// Validates The Ownership of an Asset using ItemID, OwnerID, and HashKey
//
// peer chaincode query -l golang -n mycc -c '{"Function": "ValidateItemOwnership", "Args": ["1000", "100", "tGEBaZuKUBmwTjzNEyd+nr/fPUASuVJAZ1u7gha5fJg="]}'
//
/////////////////////////////////////////////////////////////////////////////////////////
func ValidateItemOwnership(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	var err error

	if len(args) < 3 {
		fmt.Println("ValidateItemOwnership() : Requires 3 arguments Item#, Owner# and Key ")
		return shim.Error("ValidateItemOwnership() : Requires 3 arguments Item#, Owner# and Key")
	}

	// Get the Object Information
	Avalbytes, err := QueryObject(stub, "Item", []string{args[0]})
	if err != nil {
		fmt.Println("ValidateItemOwnership() : Failed to Query Object ")
		jsonResp := "{\"Error\":\"Failed to get  Object Data for " + args[0] + "\"}"
		return shim.Error(jsonResp)
	}

	if Avalbytes == nil {
		fmt.Println("ValidateItemOwnership() : Incomplete Query Object ")
		jsonResp := "{\"Error\":\"Incomplete information about the key for " + args[0] + "\"}"
		return shim.Error(jsonResp)
	}

	myItem, err := JSONtoAR(Avalbytes)
	if err != nil {
		fmt.Println("ValidateItemOwnership() : Failed to Query Object ")
		jsonResp := "{\"Error\":\"Failed to get  Object Data for " + args[0] + "\"}"
		return shim.Error(jsonResp)
	}

	myKey := GetKeyValue(Avalbytes, "AES_Key")
	fmt.Println("Key String := ", myKey)

	if myKey != args[2] {
		fmt.Println("ValidateItemOwnership() : Key does not match supplied key ", args[2], " - ", myKey)
		jsonResp := "{\"Error\":\"ValidateItemOwnership() : Key does not match asset owner supplied key  " + args[0] + "\"}"
		return shim.Error(jsonResp)
	}

	if myItem.CurrentOwnerID != args[1] {
		fmt.Println("ValidateItemOwnership() : ValidateItemOwnership() : Owner-Id does not match supplied ID ", args[1])
		jsonResp := "{\"Error\":\"ValidateItemOwnership() : Owner-Id does not match supplied ID " + args[0] + "\"}"
		return shim.Error(jsonResp)
	}

	fmt.Print("ValidateItemOwnership() : Response : Successful - \n")
	return shim.Success(Avalbytes)
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
// Retrieve Auction Information
// This query runs against the AuctionTable
// ./peer chaincode query -l golang -n mycc -c '{"Function": "GetAuctionRequest", "Args": ["1111"]}'
// There are two other tables just for query purposes - AucInitTable, AucOpenTable
//
/////////////////////////////////////////////////////////////////////////////////////////////////////
func GetAuctionRequest(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	var err error

	// Get the Objects and Display it
	Avalbytes, err := QueryObject(stub, "Auction", args)
	if err != nil {
		fmt.Println("GetAuctionRequest() : Failed to Query Object ")
		jsonResp := "{\"Error\":\"Failed to get  Object Data for " + args[0] + "\"}"
		return shim.Error(jsonResp)
	}

	if Avalbytes == nil {
		fmt.Println("GetAuctionRequest() : Incomplete Query Object ")
		jsonResp := "{\"Error\":\"Incomplete information about the key for " + args[0] + "\"}"
		return shim.Error(jsonResp)
	}

	fmt.Println("GetAuctionRequest() : Response : Successful - \n")
	return shim.Success(Avalbytes)
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Retrieve a Bid based on two keys - AucID, BidNo
// A Bid has two Keys - The Auction Request Number and Bid Number
// ./peer chaincode query -l golang -n mycc -c '{"Function": "GetLastBid", "Args": ["1111", "1"]}'
//
///////////////////////////////////////////////////////////////////////////////////////////////////
func GetBid(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	var err error

	// Check there are 2 Arguments provided as per the struct - two are computed
	// See example
	if len(args) < 2 {
		fmt.Println("GetBid(): Incorrect number of arguments. Expecting 2 ")
		fmt.Println("GetBid(): ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetBid\", \"Args\": [\"1111\",\"6\"]}'")
		return shim.Error("GetBid(): Incorrect number of arguments. Expecting 2 ")
	}

	// Get the Objects and Display it
	Avalbytes, err := QueryObject(stub, "Bid", args)
	if err != nil {
		fmt.Println("GetBid() : Failed to Query Object ")
		jsonResp := "{\"Error\":\"Failed to get  Object Data for " + args[0] + "\"}"
		return shim.Error(jsonResp)
	}

	if Avalbytes == nil {
		fmt.Println("GetBid() : Incomplete Query Object ")
		jsonResp := "{\"Error\":\"Incomplete information about the key for " + args[0] + "\"}"
		return shim.Error(jsonResp)
	}

	fmt.Println("GetBid() : Response : Successful -")
	return shim.Success(Avalbytes)
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Retrieve Auction Closeout Information. When an Auction closes
// The highest bid is retrieved and converted to a Transaction
//  ./peer chaincode query -l golang -n mycc -c '{"Function": "GetTransaction", "Args": ["1111"]}'
//
///////////////////////////////////////////////////////////////////////////////////////////////////
func GetTransaction(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	//var err error

	// Get the Objects and Display it
	Avalbytes, err := QueryObject(stub, "Trans", args)
	if Avalbytes == nil {
		fmt.Println("GetTransaction() : Incomplete Query Object ")
		jsonResp := "{\"Error\":\"Incomplete information about the key for " + args[0] + "\"}"
		return shim.Error(jsonResp)
	}

	if err != nil {
		fmt.Println("GetTransaction() : Failed to Query Object ")
		jsonResp := "{\"Error\":\"Failed to get  Object Data for " + args[0] + "\"}"
		return shim.Error(jsonResp)
	}

	fmt.Println("GetTransaction() : Response : Successful")
	return shim.Success(Avalbytes)
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Create a User Object. The first step is to have users
// registered
// There are different types of users - Traders (TRD), Auction Houses (AH)
// Shippers (SHP), Insurance Companies (INS), Banks (BNK)
// While this version of the chain code does not enforce strict validation
// the business process recommends validating each persona for the service
// they provide or their participation on the auction blockchain, future enhancements will do that
// ./peer chaincode invoke -l golang -n mycc -c '{"Function": "PostUser", "Args":["100", "USER", "Ashley Hart", "TRD",  "Morrisville Parkway, #216, Morrisville, NC 27560", "9198063535", "ashley@itpeople.com", "SUNTRUST", "00017102345", "0234678"]}'
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

func PostUser(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	record, err := CreateUserObject(args[0:]) //
	if err != nil {
		return shim.Error(err.Error())
	}
	buff, err := UsertoJSON(record) //

	if err != nil {
		error_str := "PostuserObject() : Failed Cannot create object buffer for write : " + args[1]
		fmt.Println(error_str)
		return shim.Error(error_str)
	} else {
		// Update the ledger with the Buffer Data
		// err = stub.PutState(args[0], buff)
		keys := []string{args[0]}
		err = UpdateObject(stub, "User", keys, buff)
		if err != nil {
			fmt.Println("PostUser() : write error while inserting record")
			return shim.Error("PostUser() : write error while inserting record : Error - " + err.Error())
		}

		// Post Entry into UserCat- i.e. User Category Table
		keys = []string{"2016", args[3], args[0]}
		err = UpdateObject(stub, "UserCat", keys, buff)
		if err != nil {
			error_str := "PostUser() : write error while inserting recordinto UserCat"
			fmt.Println(error_str)
			return shim.Error(error_str)
		}
	}

	return shim.Success(buff)
}

func CreateUserObject(args []string) (UserObject, error) {

	var err error
	var aUser UserObject

	// Check there are 11 Arguments
	if len(args) != 11 {
		fmt.Println("CreateUserObject(): Incorrect number of arguments. Expecting 11 ")
		return aUser, errors.New("CreateUserObject() : Incorrect number of arguments. Expecting 11 ")
	}

	// Validate UserID is an integer

	_, err = strconv.Atoi(args[0])
	if err != nil {
		return aUser, errors.New("CreateUserObject() : User ID should be an integer")
	}

	aUser = UserObject{args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]}
	fmt.Println("CreateUserObject() : User Object : ", aUser)

	return aUser, nil
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Create a master Object of the Item
// Since the Owner Changes hands, a record has to be written for each
// Transaction with the updated Encryption Key of the new owner
// Example
//./peer chaincode invoke -l golang -n mycc -c '{"Function": "PostItem", "Args":["1000", "ARTINV", "Shadows by Asppen", "Asppen Messer", "20140202", "Original", "Landscape" , "Canvas", "15 x 15 in", "sample_7.png","$600", "100", "2016-02-02 03:000:00"]}'
/////////////////////////////////////////////////////////////////////////////////////////////////////////////

func PostItem(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	itemObject, err := CreateItemObject(args[0:])
	if err != nil {
		fmt.Println("PostItem(): Cannot create item object \n")
		return shim.Error("PostItem(): Cannot create item object")
	}

	// Check if the Owner ID specified is registered and valid
	response := ValidateMember(stub, itemObject.CurrentOwnerID)
	ownerInfo := response.Payload
	fmt.Println("Owner information  ", ownerInfo, itemObject.CurrentOwnerID)
	if response.Status != shim.OK {
		error_str := "PostItem() : Failed Owner information not found for " + itemObject.CurrentOwnerID
		fmt.Println(error_str)
		return shim.Error(error_str)
	}

	// Convert Item Object to JSON
	buff, err := ARtoJSON(itemObject) //
	if err != nil {
		error_str := "PostItem() : Failed Cannot create object buffer for write : " + args[1]
		fmt.Println(error_str)
		return shim.Error(error_str)
	} else {
		// Update the ledger with the Buffer Data
		// err = stub.PutState(args[0], buff)
		keys := []string{args[0]}
		err = UpdateObject(stub, "Item", keys, buff)
		if err != nil {
			fmt.Println("PostItem() : write error while inserting record\n")
			return shim.Error("PostItem() : write error while inserting record : " + err.Error())
		}

		// Put an entry into the Item History Table
		response := PostItemLog(stub, itemObject, "INITIAL", "DEFAULT", args[12])
		if response.Status != shim.OK {
			fmt.Println("PostItemLog() : write error while inserting record\n")
			return shim.Error("PostItemLog() : write error while inserting record : Error : " + err.Error())
		}

		// Post Entry into ItemCatTable - i.e. Item Category Table
		// The first key 2016 is a dummy (band aid) key to extract all values
		keys = []string{"2016", args[6], args[0]}
		err = UpdateObject(stub, "ItemCat", keys, buff)
		if err != nil {
			fmt.Println("PostItem() : Write error while inserting record into ItemCat \n")
			return shim.Error("PostItem() : Write error while inserting record into ItemCat :   Error : " + err.Error())
		}
	}

	secret_key, _ := json.Marshal(itemObject.AES_Key)
	fmt.Println(string(secret_key))
	return shim.Success(secret_key)
}

func CreateItemObject(args []string) (ItemObject, error) {

	var err error
	var myItem ItemObject

	// Check there are 13 Arguments provided as per the struct - two are computed
	if len(args) != 13 {
		fmt.Println("CreateItemObject(): Incorrect number of arguments. Expecting 13 ")
		return myItem, errors.New("CreateItemObject(): Incorrect number of arguments. Expecting 13 ")
	}

	// Validate ItemID is an integer

	_, err = strconv.Atoi(args[0])
	if err != nil {
		fmt.Println("CreateItemObject(): ART ID should be an integer create failed! ")
		return myItem, errors.New("CreateItemObject(): ART ID should be an integer create failed!")
	}

	// Validate Picture File exists based on the name provided
	// Looks for file in current directory of application and must be fixed for other locations

	// Validate Picture File exists based on the name provided
	// Looks for file in current directory of application and must be fixed for other locations
	imagePath := args[9]
	if _, err := os.Stat(imagePath); err == nil {
		fmt.Println(imagePath, "  exists!")
	} else {
		fmt.Println("CreateItemObject(): Cannot find or load Picture File = %s :  %s\n", imagePath, err)
		return myItem, errors.New("CreateItemObject(): ART Picture File not found " + imagePath)
	}

	// Get the Item Image and convert it to a byte array
	imagebytes, fileType := ImageToByteArray(imagePath)

	// Generate a new key and encrypt the image

	AES_key, _ := GenAESKey()
	AES_enc := Encrypt(AES_key, imagebytes)

	// Append the AES Key, The Encrypted Image Byte Array and the file type
	myItem = ItemObject{args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], AES_enc, AES_key, fileType, args[10], args[11], args[12]}

	fmt.Println("CreateItemObject(): Item Object created: ", myItem.ItemID, myItem.AES_Key)

	// Code to Validate the Item Object)
	// If User presents Crypto Key then key is used to validate the picture that is stored as part of the title
	// TODO

	return myItem, nil
}

///////////////////////////////////////////////////////////////////////////////////
// Since the Owner Changes hands, a record has to be written for each
// Transaction with the updated Encryption Key of the new owner
// This function is internally invoked by PostTransaction and is not a Public API
///////////////////////////////////////////////////////////////////////////////////

func UpdateItemObject(stub shim.ChaincodeStubInterface, ar []byte, hammerPrice string, buyer string) pb.Response {

	var err error
	myItem, err := JSONtoAR(ar)
	if err != nil {
		fmt.Println("UpdateItemObject() : Failed to create Art Record Object from JSON ")
		return shim.Error("UpdateItemObject() : Failed to create Art Record Object from JSON : Error : " + err.Error())
	}

	// Insert logic to  re-encrypt image by first fetching the current Key
	CurrentAES_Key := myItem.AES_Key
	// Decrypt Image and Save Image in a file
	image := Decrypt(CurrentAES_Key, myItem.ItemImage)

	// Get a New Key & Encrypt Image with New Key
	myItem.AES_Key, _ = GenAESKey()
	myItem.ItemImage = Encrypt(myItem.AES_Key, image)

	// Update the owner to the Buyer and update price to auction hammer price
	myItem.ItemBasePrice = hammerPrice
	myItem.CurrentOwnerID = buyer

	ar, err = ARtoJSON(myItem)
	// keys := []string{myItem.ItemID, myItem.CurrentOwnerID}    // Was the original in v0.6
	keys := []string{myItem.ItemID}
	err = ReplaceObject(stub, "Item", keys, ar)
	if err != nil {
		fmt.Println("UpdateItemObject() : Failed ReplaceObject in ItemTable into Blockchain ")
		return shim.Error("UpdateItemObject() : Failed ReplaceObject in ItemTable into Blockchain : Error : " + err.Error())
	}
	fmt.Println("UpdateItemObject() : ReplaceObject in Item successful ")

	// Update entry in Item Category Table as it holds the Item object as wekk
	keys = []string{"2016", myItem.ItemSubject, myItem.ItemID}
	err = ReplaceObject(stub, "ItemCat", keys, ar)
	if err != nil {
		fmt.Println("UpdateItemObject() : Failed ReplaceObject in ItemCategory into Blockchain ")
		return shim.Error("UpdateItemObject() : Failed ReplaceObject in ItemCategory into Blockchain : Error : " + err.Error())
	}

	fmt.Println("UpdateItemObject() : ReplaceObject in ItemCategory successful ")
	return shim.Success(myItem.AES_Key)
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Obtain Asset Details and Validate Item
// Transfer Item to new owner - no change in price  - In the example XFER is the recType
// ./peer chaincode invoke -l golang -n mycc -c '{"Function": "TransferItem", "Args": ["1000", "100", "tGEBaZuKUBmwTjzNEyd+nr/fPUASuVJAZ1u7gha5fJg=", "300", "XFER"]}'
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
func TransferItem(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	var err error

	if len(args) < 6 {
		fmt.Println("TransferItem() : Requires 6 arguments Item#, Owner#, Key#, newOwnerID#, XFER \n")
		return shim.Error("TransferItem() : Requires 6 arguments Item#, Owner#, Key#, newOwnerID#, XFER")
	}

	// Let us make sure that the Item is not on Auction
	err = VerifyIfItemIsOnAuction(stub, args[0])
	if err != nil {
		error_str := "TransferItem() : Failed Item is either initiated or opened for Auction " + args[0]
		fmt.Println(error_str)
		return shim.Error(error_str + ": Error : " + err.Error())
	}

	// Validate New Owner's ID
	response := ValidateMember(stub, args[3])
	if response.Status != shim.OK {
		error_str := "TransferItem() : Failed transferee not Registered in Blockchain " + args[3]
		fmt.Println(error_str)
		return shim.Error(error_str + ": Error : " + response.Message)
	}

	// Validate Item or Asset Ownership
	response = ValidateItemOwnership(stub, "ValidateItemOwnership", args[:3])
	if response.Status != shim.OK {
		error_str := "TransferItem() : ValidateItemOwnership() : Failed to authenticate item or asset ownership"
		fmt.Println(error_str)
		return shim.Error(error_str + ": Error : " + response.Message)
	}

	ar := response.Payload
	myItem, err := JSONtoAR(ar)
	if err != nil {
		error_str := "TransferItem() : Failed to create item Object from JSON "
		fmt.Println(error_str)
		return shim.Error(error_str + ": Error : " + err.Error())
	}

	// Insert logic to  re-encrypt image by first fetching the current Key
	CurrentAES_Key := myItem.AES_Key
	// Decrypt Image and Save Image in a file
	image := Decrypt(CurrentAES_Key, myItem.ItemImage)

	// Get a New Key & Encrypt Image with New Key
	myItem.AES_Key, _ = GenAESKey()
	myItem.ItemImage = Encrypt(myItem.AES_Key, image)

	// Update the owner to the new owner transferred to
	myItem.CurrentOwnerID = args[3]

	ar, err = ARtoJSON(myItem)
	keys := []string{myItem.ItemID}
	err = ReplaceObject(stub, "Item", keys, ar)
	if err != nil {
		fmt.Println("TransferAsset() : Failed ReplaceObject in ItemTable into Blockchain ")
		return shim.Error(err.Error())
	}
	fmt.Println("TransferAsset() : ReplaceObject in Item successful ")

	// Update entry in Item Category Table as it holds the Item object as well
	keys = []string{"2016", myItem.ItemSubject, myItem.ItemID}
	err = ReplaceObject(stub, "ItemCat", keys, ar)
	if err != nil {
		fmt.Println("TransferAsset() : Failed ReplaceObject in ItemCategoryTable into Blockchain ")
		return shim.Error(err.Error())
	}

	response = PostItemLog(stub, myItem, "Transfer", args[1], args[5])
	if response.Status != shim.OK {
		fmt.Println("TransferItem() : PostItemLog() write error while inserting record\n")
		return shim.Error(err.Error())
	}

	fmt.Println("TransferAsset() : ReplaceObject in ItemCategory successful ")
	return shim.Success(myItem.AES_Key)
}

////////////////////////////////////////////////////////////////////////////////////
// Validate Item Status - Is it currently on Auction, if so Reject Transfer Request
// This can be written better - will do so if things work
// The function return the Auction ID and the Status = OPEN or INIT
////////////////////////////////////////////////////////////////////////////////////

func VerifyIfItemIsOnAuction(stub shim.ChaincodeStubInterface, itemID string) error {

	response := GetListOfOpenAucs(stub, "AucOpen", []string{"2016"})
	if response.Status != shim.OK {
		return fmt.Errorf("VerifyIfItemIsOnAuction() operation failed. Error retrieving values from AucOpen: %s", response.Message)
	}

	rows := response.Payload
	tlist := make([]AuctionRequest, len(rows))
	err := json.Unmarshal([]byte(rows), &tlist)
	if err != nil {
		fmt.Println("VerifyIfItemIsOnAuction: Unmarshal failed : ", err)
		return fmt.Errorf("VerifyIfItemIsOnAuction: operation failed. Error un-marshaling JSON: %s", err)
	}

	for i := 0; i < len(tlist); i++ {
		ar := tlist[i]

		// Compare Auction IDs
		if ar.ItemID == itemID {
			fmt.Println("VerifyIfItemIsOnAuction() Failed : Ummarshall error")
			return fmt.Errorf("VerifyIfItemIsOnAuction() operation failed. %s", itemID)
		}
	}

	// Now Check if an Auction Has been inititiated
	// If so , it has to be removed from Auction for a Transfer

	response = GetListOfInitAucs(stub, "AucInit", []string{"2016"})
	if response.Status != shim.OK {
		return fmt.Errorf("VerifyIfItemIsOnAuction() operation failed. Error retrieving values from AucInit: %s", err)
	}

	rows = response.Payload
	tlist = make([]AuctionRequest, len(rows))
	err = json.Unmarshal([]byte(rows), &tlist)
	if err != nil {
		fmt.Println("VerifyIfItemIsOnAuction() Unmarshal failed : ", err)
		return fmt.Errorf("VerifyIfItemIsOnAuction: operation failed. Error un-marshaling JSON: %s", err)
	}

	for i := 0; i < len(tlist); i++ {
		ar := tlist[i]
		if err != nil {
			fmt.Println("VerifyIfItemIsOnAuction() Failed : Ummarshall error")
			return fmt.Errorf("VerifyIfItemIsOnAuction() operation failed. %s", err)
		}

		// Compare Auction IDs
		if ar.ItemID == itemID {
			return fmt.Errorf("VerifyIfItemIsOnAuction() operation failed.")
		}
	}

	return nil
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// POSTS A LOG ENTRY Every Time the Item is transacted
// Valid Status for ItemLog =  OnAuc, OnSale, NA, INITIAL
// Valid AuctionedBy: This value is set to "DEFAULT" but when it is put on auction Auction House ID is assigned
// PostItemLog IS NOT A PUBLIC API and is invoked every time some event happens in the Item's life
// The currentDateTime must be provided by Client
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

func PostItemLog(stub shim.ChaincodeStubInterface, item ItemObject, status string, ah string, currentDateTime string) pb.Response {

	iLog := ItemToItemLog(item, currentDateTime)
	iLog.Status = status
	iLog.AuctionedBy = ah

	buff, err := ItemLogtoJSON(iLog)
	if err != nil {
		fmt.Println("PostItemLog() : Failed Cannot create object buffer for write : ", item.ItemID)
		return shim.Error("PostItemLog(): Failed Cannot create object buffer for write : " + item.ItemID)
	} else {
		// Update the ledger with the Buffer Data
		keys := []string{iLog.ItemID, iLog.Status, iLog.AuctionedBy, currentDateTime}
		err = UpdateObject(stub, "ItemHistory", keys, buff)
		if err != nil {
			fmt.Println("PostItemLog() : write error while inserting record\n")
			return shim.Error(err.Error())
		}
	}
	return shim.Success(buff)
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Create an Auction Request
// The owner of an Item, when ready to put the item on an auction
// will create an auction request  and specify a  auction house.
//
// ./peer chaincode invoke -l golang -n mycc -c '{"Function": "PostAuctionRequest", "Args":["1111", "AUCREQ", "1700", "200", "400", "04012016", "1200", "INIT", "2016-05-20 11:00:00.3 +0000 UTC","2016-05-23 11:00:00.3 +0000 UTC", "2016-05-23 11:00:00.3 +0000 UTC"]}'
//
// The start and end time of the auction are actually assigned when the auction is opened  by OpenAuctionForBids()
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

func PostAuctionRequest(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	ar, err := CreateAuctionRequest(args[0:])
	if err != nil {
		return shim.Error(err.Error())
	}

	// Let us make sure that the Item is not on Auction
	err = VerifyIfItemIsOnAuction(stub, ar.ItemID)
	if err != nil {
		fmt.Println("PostAuctionRequest() : Failed Item is either initiated or opened for Auction ", args[0])
		return shim.Error(err.Error())
	}

	// Validate Auction House to check it is a registered User
	response := ValidateMember(stub, ar.AuctionHouseID)
	if response.Status != shim.OK {
		fmt.Println("PostAuctionRequest() : Failed Auction House not Registered in Blockchain ", ar.AuctionHouseID)
		return shim.Error(err.Error())
	}

	aucHouse := response.Payload
	fmt.Println("Auction House information  ", aucHouse, " ID: ", ar.AuctionHouseID)

	// Validate Item record
	response = ValidateItemSubmission(stub, ar.ItemID)
	if response.Status != shim.OK {
		fmt.Println("PostAuctionRequest() : Failed Could not Validate Item Object in Blockchain ", ar.ItemID)
		return shim.Error(err.Error())
	}

	itemObject := response.Payload

	// Convert AuctionRequest to JSON
	buff, err := AucReqtoJSON(ar) // Converting the auction request struct to []byte array
	if err != nil {
		fmt.Println("PostAuctionRequest() : Failed Cannot create object buffer for write : ", args[1])
		return shim.Error("PostAuctionRequest(): Failed Cannot create object buffer for write : " + args[1])
	} else {
		// Update the ledger with the Buffer Data
		//err = stub.PutState(args[0], buff)
		keys := []string{args[0]}
		err = UpdateObject(stub, "Auction", keys, buff)
		if err != nil {
			fmt.Println("PostAuctionRequest() : write error while inserting record\n")
			return shim.Error(err.Error())
		}

		// Post an Item Log and the Auction House ID is included in the log
		// Recall -- that by default that value is "DEFAULT"

		io, err := JSONtoAR(itemObject)
		response := PostItemLog(stub, io, "ReadyForAuc", ar.AuctionHouseID, ar.TimeStamp)
		if response.Status != shim.OK {
			fmt.Println("PostItemLog() : write error while inserting record\n")
			return shim.Error(err.Error())
		}

		//An entry is made in the AuctionInitTable that this Item has been placed for Auction
		// The UI can pull all items available for auction and the item can be Opened for accepting bids
		// The 2016 is a dummy key and has notr value other than to get all rows

		keys = []string{"2016", args[0]}
		err = UpdateObject(stub, "AucInit", keys, buff)
		if err != nil {
			fmt.Println("PostAuctionRequest() : write error while inserting record into AucInit\n")
			return shim.Error(err.Error())
		}

	}

	return shim.Success(buff)
}

func CreateAuctionRequest(args []string) (AuctionRequest, error) {
	var err error
	var aucReg AuctionRequest

	// Check there are 12 Arguments
	// See example -- The Open and Close Dates are Dummy, and will be set by open auction
	// '{"Function": "PostAuctionRequest", "Args":["1111", "AUCREQ", "1000", "200", "100", "04012016", "1200", "1800",
	//   "INIT", "2016-05-20 11:00:00.3 +0000 UTC","2016-05-23 11:00:00.3 +0000 UTC", "2016-05-23 11:00:00.3 +0000 UTC"]}'
	if len(args) != 12 {
		fmt.Println("CreateAuctionRegistrationObject(): Incorrect number of arguments. Expecting 11 ")
		return aucReg, errors.New("CreateAuctionRegistrationObject() : Incorrect number of arguments. Expecting 11 ")
	}

	// Validate UserID is an integer . I think this redundant and can be avoided

	err = validateID(args[0])
	if err != nil {
		return aucReg, errors.New("CreateAuctionRequest() : User ID should be an integer")
	}

	aucReg = AuctionRequest{args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11]}
	fmt.Println("CreateAuctionObject() : Auction Registration : ", aucReg)

	return aucReg, nil
}

//////////////////////////////////////////////////////////
// Create an Item Transaction record to process Request
// This is invoked by the CloseAuctionRequest
//
//
////////////////////////////////////////////////////////////
func PostTransaction(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	if function != "PostTransaction" {
		return shim.Error("PostTransaction(): Invalid function name. Expecting \"PostTransaction\"")
	}

	ar, err := CreateTransactionRequest(args[0:]) //
	if err != nil {
		return shim.Error(err.Error())
	}

	// Validate buyer's ID
	response := ValidateMember(stub, ar.UserId)
	if response.Status != shim.OK {
		fmt.Println("PostTransaction() : Failed Buyer not Registered in Blockchain ", ar.UserId)
		return shim.Error(err.Error())
	}

	buyer := response.Payload

	fmt.Println("PostTransaction(): Validated Buyer information Successfully ", buyer, ar.UserId)

	// Validate Item record
	response = ValidateItemSubmission(stub, ar.ItemID)
	if response.Status != shim.OK {
		fmt.Println("PostTransaction() : Failed Could not Validate Item Object in Blockchain ", ar.ItemID)
		return shim.Error(err.Error())
	}

	lastUpdatedItemOBCObject := response.Payload
	fmt.Println("PostTransaction() : Validated Item Object in Blockchain Successfully", ar.ItemID)

	// Update Item Object with new Owner Key
	response = UpdateItemObject(stub, lastUpdatedItemOBCObject, ar.HammerPrice, ar.UserId)
	newKey := response.Payload
	if response.Status != shim.OK {
		fmt.Println("PostTransaction() : Failed to update Item Master Object in Blockchain ", ar.ItemID)
		return shim.Error(err.Error())
	} else {
		// Write New Key to file
		fmt.Println("PostTransaction() : New encryption Key is  ", newKey)
	}

	fmt.Println("PostTransaction() : Updated Item Master Object in Blockchain Successfully", ar.ItemID)

	// Post an Item Log
	itemObject, err := JSONtoAR(lastUpdatedItemOBCObject)
	if err != nil {
		fmt.Println("PostTransaction() : Conversion error JSON to ItemRecord\n")
		return shim.Error(err.Error())
	}

	// A life cycle event is added to say that the Item is no longer on auction
	itemObject.ItemBasePrice = ar.HammerPrice
	itemObject.CurrentOwnerID = ar.UserId

	response = PostItemLog(stub, itemObject, "NA", "DEFAULT", args[5])
	if response.Status != shim.OK {
		fmt.Println("PostTransaction() : write error while inserting item log record\n")
		return shim.Error(err.Error())
	}

	fmt.Println("PostTransaction() : Inserted item log record Successfully", ar.ItemID)

	// Convert Transaction Object to JSON
	buff, err := TrantoJSON(ar) //
	if err != nil {
		fmt.Println("GetObjectBuffer() : Failed to convert Transaction Object to JSON ", args[0])
		return shim.Error(err.Error())
	}

	// Update the ledger with the Buffer Data
	keys := []string{args[0], args[3]}
	err = UpdateObject(stub, "Trans", keys, buff)
	if err != nil {
		fmt.Println("PostTransaction() : write error while inserting record\n")
		return shim.Error(err.Error())
	}

	fmt.Println("PostTransaction() : Posted Transaction Record Successfully\n")

	// Returns New Key. To get Transaction Details, run GetTransaction

	secret_key, _ := json.Marshal(newKey)
	fmt.Println(string(secret_key))
	return shim.Success(secret_key)

}

func CreateTransactionRequest(args []string) (ItemTransaction, error) {

	var at ItemTransaction

	// Check there are 9 Arguments
	if len(args) != 9 {
		fmt.Println("CreateTransactionRequest(): Incorrect number of arguments. Expecting 9 ")
		return at, errors.New("CreateTransactionRequest() : Incorrect number of arguments. Expecting 9 ")
	}

	at = ItemTransaction{args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]}
	fmt.Println("CreateTransactionRequest() : Transaction Request: ", at)

	return at, nil
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Create a Bid Object
// Once an Item has been opened for auction, bids can be submitted as long as the auction is "OPEN"
//./peer chaincode invoke -l golang -n mycc -c '{"Function": "PostBid", "Args":["1111", "BID", "1", "1000", "300", "1200", "2017-01-23 14:00:00.3 +0000 UTC"]}'
//./peer chaincode invoke -l golang -n mycc -c '{"Function": "PostBid", "Args":["1111", "BID", "2", "1000", "400", "3000","2017-01-23 14:00:00.3 +0000 UTC"]}'
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

func PostBid(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	bid, err := CreateBidObject(args[0:]) //
	if err != nil {
		return shim.Error(err.Error())
	}

	// Reject the Bid if the Buyer Information Is not Valid or not registered on the Block Chain
	response := ValidateMember(stub, args[4])
	if response.Status != shim.OK {
		fmt.Println("PostBid() : Failed Buyer not registered on the block-chain ", args[4])
		return shim.Error(err.Error())
	}

	buyerInfo := response.Payload
	fmt.Println("Buyer information  ", buyerInfo, "  ", args[4])

	///////////////////////////////////////
	// Reject Bid if Auction is not "OPEN"
	///////////////////////////////////////
	response = GetAuctionRequest(stub, "GetAuctionRequest", []string{args[0]})
	if response.Status != shim.OK {
		fmt.Println("PostBid() : Cannot find Auction record ", args[0])
		return shim.Error("PostBid(): Cannot find Auction record : " + args[0])
	}

	RBytes := response.Payload

	aucR, err := JSONtoAucReq(RBytes)
	if err != nil {
		fmt.Println("PostBid() : Cannot UnMarshall Auction record")
		return shim.Error("PostBid(): Cannot UnMarshall Auction record: " + args[0])
	}

	if aucR.Status != "OPEN" {
		fmt.Println("PostBid() : Cannot accept Bid as Auction is not OPEN ", args[0])
		return shim.Error("PostBid(): Cannot accept Bid as Auction is not OPEN : " + args[0])
	}

	///////////////////////////////////////////////////////////////////
	// Reject Bid if the time bid was received is > Auction Close Time
	///////////////////////////////////////////////////////////////////
	if tCompare(bid.BidTime, aucR.CloseDate) == false {
		fmt.Println("PostBid() Failed : BidTime past the Auction Close Time")
		error_str := fmt.Sprintf("PostBid() Failed : BidTime past the Auction Close Time %s, %s", bid.BidTime, aucR.CloseDate)
		return shim.Error(error_str)
	}

	//////////////////////////////////////////////////////////////////
	// Reject Bid if Item ID on Bid does not match Item ID on Auction
	//////////////////////////////////////////////////////////////////
	if aucR.ItemID != bid.ItemID {
		fmt.Println("PostBid() Failed : Item ID mismatch on bid. Bid Rejected")
		return shim.Error("PostBid() : Item ID mismatch on Bid. Bid Rejected")
	}

	//////////////////////////////////////////////////////////////////////
	// Reject Bid if Bid Price is less than Reserve Price
	// Convert Bid Price and Reserve Price to Integer (TODO - Float)
	//////////////////////////////////////////////////////////////////////
	bp, err := strconv.Atoi(bid.BidPrice)
	if err != nil {
		fmt.Println("PostBid() Failed : Bid price should be an integer")
		return shim.Error("PostBid() : Bid price should be an integer")
	}

	hp, err := strconv.Atoi(aucR.ReservePrice)
	if err != nil {
		return shim.Error("PostItem() : Reserve Price should be an integer")
	}

	// Check if Bid Price is > Auction Request Reserve Price
	if bp < hp {
		return shim.Error("PostItem() : Bid Price must be greater than Reserve Price")
	}

	////////////////////////////
	// Post or Accept the Bid
	////////////////////////////
	buff, err := BidtoJSON(bid) //

	if err != nil {
		fmt.Println("PostBid() : Failed Cannot create object buffer for write : ", args[1])
		return shim.Error("PostBid(): Failed Cannot create object buffer for write : " + args[1])
	} else {
		// Update the ledger with the Buffer Data
		// err = stub.PutState(args[0], buff)
		keys := []string{args[0], args[2]}
		err = UpdateObject(stub, "Bid", keys, buff)
		if err != nil {
			fmt.Println("PostBid() : write error while inserting record\n")
			return shim.Error(err.Error())
		}
	}

	return shim.Success(buff)
}

func CreateBidObject(args []string) (Bid, error) {
	var err error
	var aBid Bid

	// Check there are 7 Arguments
	// See example
	if len(args) != 7 {
		fmt.Println("CreateBidObject(): Incorrect number of arguments. Expecting 7 ")
		return aBid, errors.New("CreateBidObject() : Incorrect number of arguments. Expecting 7 ")
	}

	// Validate Bid is an integer

	_, err = strconv.Atoi(args[0])
	if err != nil {
		return aBid, errors.New("CreateBidObject() : Bid ID should be an integer")
	}

	_, err = strconv.Atoi(args[2])
	if err != nil {
		return aBid, errors.New("CreateBidObject() : Bid ID should be an integer")
	}

	// bidTime = args[6]  sent by the client
	aBid = Bid{args[0], args[1], args[2], args[3], args[4], args[5], args[6]}
	fmt.Println("CreateBidObject() : Bid Object : ", aBid)

	return aBid, nil
}

//////////////////////////////////////////////////////////
// JSON To args[] - return a map of the JSON string
//////////////////////////////////////////////////////////
func JSONtoArgs(Avalbytes []byte) (map[string]interface{}, error) {

	var data map[string]interface{}

	if err := json.Unmarshal(Avalbytes, &data); err != nil {
		return nil, err
	}

	return data, nil
}

//////////////////////////////////////////////////////////
// Variation of the above - return value from a JSON string
//////////////////////////////////////////////////////////

func GetKeyValue(Avalbytes []byte, key string) string {
	var dat map[string]interface{}
	if err := json.Unmarshal(Avalbytes, &dat); err != nil {
		panic(err)
	}

	val := dat[key].(string)
	return val
}

//////////////////////////////////////////////////////////
// Time and Date Comparison
// tCompare("2016-06-28 18:40:57", "2016-06-27 18:45:39")
//////////////////////////////////////////////////////////
func tCompare(t1 string, t2 string) bool {

	layout := "2006-01-02 15:04:05"
	bidTime, err := time.Parse(layout, t1)
	if err != nil {
		fmt.Println("tCompare() Failed : time Conversion error on t1")
		return false
	}

	aucCloseTime, err := time.Parse(layout, t2)
	if err != nil {
		fmt.Println("tCompare() Failed : time Conversion error on t2")
		return false
	}

	if bidTime.Before(aucCloseTime) {
		return true
	}

	return false
}

//////////////////////////////////////////////////////////
// Converts JSON String to an ART Object
//////////////////////////////////////////////////////////
func JSONtoAR(data []byte) (ItemObject, error) {

	ar := ItemObject{}
	err := json.Unmarshal([]byte(data), &ar)
	if err != nil {
		fmt.Println("Unmarshal failed : ", err)
	}

	return ar, err
}

//////////////////////////////////////////////////////////
// Converts an ART Object to a JSON String
//////////////////////////////////////////////////////////
func ARtoJSON(ar ItemObject) ([]byte, error) {

	ajson, err := json.Marshal(ar)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}
	return ajson, nil
}

//////////////////////////////////////////////////////////
// Converts an BID to a JSON String
//////////////////////////////////////////////////////////
func ItemLogtoJSON(item ItemLog) ([]byte, error) {

	ajson, err := json.Marshal(item)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}
	return ajson, nil
}

//////////////////////////////////////////////////////////
// Converts an User Object to a JSON String
//////////////////////////////////////////////////////////
func JSONtoItemLog(ithis []byte) (ItemLog, error) {

	item := ItemLog{}
	err := json.Unmarshal(ithis, &item)
	if err != nil {
		fmt.Println("JSONtoAucReq error: ", err)
		return item, err
	}
	return item, err
}

//////////////////////////////////////////////////////////
// Converts an Auction Request to a JSON String
//////////////////////////////////////////////////////////
func AucReqtoJSON(ar AuctionRequest) ([]byte, error) {

	ajson, err := json.Marshal(ar)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}
	return ajson, nil
}

//////////////////////////////////////////////////////////
// Converts an User Object to a JSON String
//////////////////////////////////////////////////////////
func JSONtoAucReq(areq []byte) (AuctionRequest, error) {

	ar := AuctionRequest{}
	err := json.Unmarshal(areq, &ar)
	if err != nil {
		fmt.Println("JSONtoAucReq error: ", err)
		return ar, err
	}
	return ar, err
}

//////////////////////////////////////////////////////////
// Converts an BID to a JSON String
//////////////////////////////////////////////////////////
func BidtoJSON(myHand Bid) ([]byte, error) {

	ajson, err := json.Marshal(myHand)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}
	return ajson, nil
}

//////////////////////////////////////////////////////////
// Converts an User Object to a JSON String
//////////////////////////////////////////////////////////
func JSONtoBid(areq []byte) (Bid, error) {

	myHand := Bid{}
	err := json.Unmarshal(areq, &myHand)
	if err != nil {
		fmt.Println("JSONtoAucReq error: ", err)
		return myHand, err
	}
	return myHand, err
}

//////////////////////////////////////////////////////////
// Converts an User Object to a JSON String
//////////////////////////////////////////////////////////
func UsertoJSON(user UserObject) ([]byte, error) {

	ajson, err := json.Marshal(user)
	if err != nil {
		fmt.Println("UsertoJSON error: ", err)
		return nil, err
	}
	fmt.Println("UsertoJSON created: ", ajson)
	return ajson, nil
}

//////////////////////////////////////////////////////////
// Converts an User Object to a JSON String
//////////////////////////////////////////////////////////
func JSONtoUser(user []byte) (UserObject, error) {

	ur := UserObject{}
	err := json.Unmarshal(user, &ur)
	if err != nil {
		fmt.Println("UsertoJSON error: ", err)
		return ur, err
	}
	fmt.Println("UsertoJSON created: ", ur)
	return ur, err
}

//////////////////////////////////////////////////////////
// Converts an Item Transaction to a JSON String
//////////////////////////////////////////////////////////
func TrantoJSON(at ItemTransaction) ([]byte, error) {

	ajson, err := json.Marshal(at)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}
	return ajson, nil
}

//////////////////////////////////////////////////////////
// Converts an Trans Object to a JSON String
//////////////////////////////////////////////////////////
func JSONtoTran(areq []byte) (ItemTransaction, error) {

	at := ItemTransaction{}
	err := json.Unmarshal(areq, &at)
	if err != nil {
		fmt.Println("JSONtoTran error: ", err)
		return at, err
	}
	return at, err
}

//////////////////////////////////////////////
// Validates an ID for Well Formed
//////////////////////////////////////////////

func validateID(id string) error {
	// Validate UserID is an integer

	_, err := strconv.Atoi(id)
	if err != nil {
		return errors.New("validateID(): User ID should be an integer")
	}
	return nil
}

//////////////////////////////////////////////
// Create an ItemLog from Item
//////////////////////////////////////////////

func ItemToItemLog(io ItemObject, cdt string) ItemLog {

	iLog := ItemLog{}
	iLog.ItemID = io.ItemID
	iLog.Status = "INITIAL"
	iLog.AuctionedBy = "DEFAULT"
	iLog.RecType = "ILOG"
	iLog.ItemDesc = io.ItemDesc
	iLog.CurrentOwner = io.CurrentOwnerID
	iLog.Date = cdt

	return iLog
}

//////////////////////////////////////////////
// Convert Bid to Transaction for Posting
//////////////////////////////////////////////

func BidtoTransaction(bid Bid) ItemTransaction {

	var t ItemTransaction
	t.AuctionID = bid.AuctionID
	t.RecType = "POSTTRAN"
	t.ItemID = bid.ItemID
	t.TransType = "SALE"
	t.UserId = bid.BuyerID
	// Ideally SystemChain Code must provide a TimeStamp Function
	t.TransDate = bid.BidTime
	t.HammerTime = bid.BidTime
	t.HammerPrice = bid.BidPrice
	t.Details = "The Highest Bidder does not always win"

	return t
}

////////////////////////////////////////////////////////////////////////////
// Validate if the User Information Exists
// in the block-chain
////////////////////////////////////////////////////////////////////////////
func ValidateMember(stub shim.ChaincodeStubInterface, owner string) pb.Response {

	// Get the Item Objects and Display it
	// Avalbytes, err := stub.GetState(owner)
	args := []string{owner}
	Avalbytes, err := QueryObject(stub, "User", args)

	if err != nil {
		fmt.Println("ValidateMember() : Failed - Cannot find valid owner record for ART  ", owner)
		jsonResp := "{\"Error\":\"Failed to get Owner Object Data for " + owner + "\"}"
		return shim.Error(jsonResp)
	}

	if Avalbytes == nil {
		fmt.Println("ValidateMember() : Failed - Incomplete owner record for ART  ", owner)
		jsonResp := "{\"Error\":\"Failed - Incomplete information about the owner for " + owner + "\"}"
		return shim.Error(jsonResp)
	}

	fmt.Println("ValidateMember() : Validated Item Owner:\n", owner)
	return shim.Success(Avalbytes)
}

////////////////////////////////////////////////////////////////////////////
// Validate if the User Information Exists
// in the block-chain
////////////////////////////////////////////////////////////////////////////
func ValidateItemSubmission(stub shim.ChaincodeStubInterface, artId string) pb.Response {

	// Get the Item Objects and Display it
	args := []string{artId}
	Avalbytes, err := QueryObject(stub, "Item", args)
	if err != nil {
		fmt.Println("ValidateItemSubmission() : Failed - Cannot find valid owner record for ART  ", artId)
		jsonResp := "{\"Error\":\"Failed to get Owner Object Data for " + artId + "\"}"
		return shim.Error(jsonResp)
	}

	if Avalbytes == nil {
		fmt.Println("ValidateItemSubmission() : Failed - Incomplete owner record for ART  ", artId)
		jsonResp := "{\"Error\":\"Failed - Incomplete information about the owner for " + artId + "\"}"
		return shim.Error(jsonResp)
	}

	//fmt.Println("ValidateItemSubmission() : Validated Item Owner:", Avalbytes)
	return shim.Success(Avalbytes)
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
// Get List of Bids for an Auction
// in the block-chain --
// ./peer chaincode query -l golang -n mycc -c '{"Function": "GetListOfBids", "Args": ["1111"]}'
// ./peer chaincode query -l golang -n mycc -c '{"Function": "GetLastBid", "Args": ["1111"]}'
// ./peer chaincode query -l golang -n mycc -c '{"Function": "GetHighestBid", "Args": ["1111"]}'
/////////////////////////////////////////////////////////////////////////////////////////////////////
func GetListOfBids(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	rs, err := GetList(stub, "Bid", args)
	if err != nil {
		error_str := fmt.Sprintf("GetListOfBids operation failed. Error marshaling JSON: %s", err)
		return shim.Error(error_str)
	}

	defer rs.Close()

	// Iterate through result set
	var i int
	var tlist []Bid // Define a list
	for i = 0; rs.HasNext(); i++ {

		// We can process whichever return value is of interest
		responseRange, err := rs.Next()

		if err != nil {
			return shim.Success(nil)
		}
		bid, err := JSONtoBid(responseRange.Value)
		if err != nil {
			error_str := fmt.Sprintf("GetListOfBids() operation failed - Unmarshall Error. %s", err)
			fmt.Println(error_str)
			return shim.Error(error_str)
		}
		fmt.Println("GetList() : my Value : ", bid)
		tlist = append(tlist, bid)
	}

	jsonRows, err := json.Marshal(tlist)
	if err != nil {
		error_str := fmt.Sprintf("GetListOfBids() operation failed - Unmarshall Error. %s", err)
		fmt.Println(error_str)
		return shim.Error(error_str)
	}

	fmt.Println("List of Bids Requested : ", jsonRows)
	return shim.Success(jsonRows)

}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Get List of Auctions that have been initiated
// in the block-chain
// This is a fixed Query to be issued as below
// peer chaincode query -l golang -n mycc -c '{"Args": ["qGetListOfInitAucs", "2016"]}'
////////////////////////////////////////////////////////////////////////////////////////////////////////
func GetListOfInitAucs(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	rs, err := GetList(stub, "AucInit", args)
	if err != nil {
		error_str := fmt.Sprintf("GetListOfInitAucs operation failed. Error marshaling JSON: %s", err)
		return shim.Error(error_str)
	}

	defer rs.Close()

	// Iterate through result set
	var i int
	var tlist []AuctionRequest // Define a list
	for i = 0; rs.HasNext(); i++ {

		// We can process whichever return value is of interest
		responseRange, err := rs.Next()
		if err != nil {
			return shim.Success(nil)
		}
		ar, err := JSONtoAucReq(responseRange.Value)
		if err != nil {
			error_str := fmt.Sprintf("GetListOfInitAucs() operation failed - Unmarshall Error. %s", err)
			fmt.Println(error_str)
			return shim.Error(error_str)
		}
		fmt.Println("GetListOfInitAucs() : my Value : ", ar)
		tlist = append(tlist, ar)
	}

	jsonRows, err := json.Marshal(tlist)
	if err != nil {
		error_str := fmt.Sprintf("GetListOfInitAucs() operation failed - Unmarshall Error. %s", err)
		fmt.Println(error_str)
		return shim.Error(error_str)
	}

	//fmt.Println("List of Auctions Requested : ", jsonRows)
	return shim.Success(jsonRows)

}

////////////////////////////////////////////////////////////////////////////
// Get List of Open Auctions  for which bids can be supplied
// in the block-chain
// This is a fixed Query to be issued as below
// peer chaincode query -l golang -n mycc -c '{"Args": ["qGetListOfOpenAucs", "2016"]}'
////////////////////////////////////////////////////////////////////////////
func GetListOfOpenAucs(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	rs, err := GetList(stub, "AucOpen", args)
	if err != nil {
		error_str := fmt.Sprintf("GetListOfOpenAucs operation failed. Error marshaling JSON: %s", err)
		return shim.Error(error_str)
	}
	defer rs.Close()

	// Iterate through result set
	var i int
	var tlist []AuctionRequest // Define a list
	for i = 0; rs.HasNext(); i++ {

		// We can process whichever return value is of interest
		responseRange, err := rs.Next()
		if err != nil {
			return shim.Success(nil)
		}
		ar, err := JSONtoAucReq(responseRange.Value)
		if err != nil {
			error_str := fmt.Sprintf("GetListOfOpenAucs() operation failed - Unmarshall Error. %s", err)
			fmt.Println(error_str)
			return shim.Error(error_str)
		}
		fmt.Println("GetListOfOpenAucs() : my Value : ", ar)
		tlist = append(tlist, ar)
	}

	jsonRows, err := json.Marshal(tlist)
	if err != nil {
		error_str := fmt.Sprintf("GetListOfInitAucs() operation failed - Unmarshall Error. %s", err)
		fmt.Println(error_str)
		return shim.Error(error_str)
	}

	//fmt.Println("List of Open Auctions : ", jsonRows)
	return shim.Success(jsonRows)

}

////////////////////////////////////////////////////////////////////////////
// Get the Item History for an Item
// in the block-chain .. Pass the Item ID
// ./peer chaincode query -l golang -n mycc -c '{"Function": "GetItemLog", "Args": ["1000"]}'
////////////////////////////////////////////////////////////////////////////
func GetItemLog(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	// Check there are 1 Arguments provided as per the struct - two are computed
	// See example
	if len(args) < 1 {
		fmt.Println("GetItemLog(): Incorrect number of arguments. Expecting 1 ")
		fmt.Println("GetItemLog(): ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetItem\", \"Args\": [\"1111\"]}'")
		return shim.Error("CreateItemObject(): Incorrect number of arguments. Expecting 12 ")
	}

	rs, err := GetList(stub, "ItemHistory", args)
	if err != nil {
		error_str := fmt.Sprintf("GetItemLog operation failed. Error marshaling JSON: %s", err)
		return shim.Error(error_str)
	}

	defer rs.Close()

	// Iterate through result set
	var i int
	var tlist []ItemLog // Define a list
	for i = 0; rs.HasNext(); i++ {

		// We can process whichever return value is of interest
		responseRange, err := rs.Next()
		if err != nil {
			return shim.Success(nil)
		}
		il, err := JSONtoItemLog(responseRange.Value)
		if err != nil {
			error_str := fmt.Sprintf("GetItemLog() operation failed - Unmarshall Error. %s", err)
			fmt.Println(error_str)
			return shim.Error(error_str)
		}
		fmt.Println("GetItemLog() : my Value : ", il)
		tlist = append(tlist, il)
	}

	jsonRows, err := json.Marshal(tlist)
	if err != nil {
		error_str := fmt.Sprintf("GetItemLog() operation failed - Unmarshall Error. %s", err)
		fmt.Println(error_str)
		return shim.Error(error_str)
	}

	//fmt.Println("All History : ", jsonRows)
	return shim.Success(jsonRows)

}

////////////////////////////////////////////////////////////////////////////
// Get a List of Items by Category
// in the block-chain
// Input is 2016 + Category
// Categories include whatever has been defined in the Item Tables - Landscape, Modern, ...
// See Sample data
// ./peer chaincode query -l golang -n mycc -c '{"Function": "GetItemListByCat", "Args": ["2016", "Modern"]}'
////////////////////////////////////////////////////////////////////////////
func GetItemListByCat(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	// Check there are 1 Arguments provided as per the struct - two are computed
	// See example
	if len(args) < 1 {
		fmt.Println("GetItemListByCat(): Incorrect number of arguments. Expecting 1 ")
		fmt.Println("GetItemListByCat(): ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetItemListByCat\", \"Args\": [\"Modern\"]}'")
		return shim.Error("CreateItemObject(): Incorrect number of arguments. Expecting 1 ")
	}

	rs, err := GetList(stub, "ItemCat", args)
	if err != nil {
		error_str := fmt.Sprintf("GetItemListByCat operation failed. Error marshaling JSON: %s", err)
		return shim.Error(error_str)
	}

	defer rs.Close()

	// Iterate through result set
	var i int
	var tlist []ItemObject // Define a list
	for i = 0; rs.HasNext(); i++ {

		// We can process whichever return value is of interest
		responseRange, err := rs.Next()
		if err != nil {
			return shim.Success(nil)
		}
		io, err := JSONtoAR(responseRange.Value)
		if err != nil {
			error_str := fmt.Sprintf("GetItemListByCat() operation failed - Unmarshall Error. %s", err)
			fmt.Println(error_str)
			return shim.Error(error_str)
		}

		fmt.Println("GetItemListByCat() : my Value : ", io)
		tlist = append(tlist, io)
	}

	jsonRows, err := json.Marshal(tlist)
	if err != nil {
		error_str := fmt.Sprintf("GetItemListByCat() operation failed - Unmarshall Error. %s", err)
		fmt.Println(error_str)
		return shim.Error(error_str)
	}

	//fmt.Println("All Items : ", jsonRows)
	return shim.Success(jsonRows)

}

////////////////////////////////////////////////////////////////////////////
// Get a List of Users by Category
// in the block-chain
////////////////////////////////////////////////////////////////////////////
func GetUserListByCat(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	// Check there are 1 Arguments provided as per the struct - two are computed
	// See example
	if len(args) < 1 {
		fmt.Println("GetUserListByCat(): Incorrect number of arguments. Expecting 1 ")
		fmt.Println("GetUserListByCat(): ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetUserListByCat\", \"Args\": [\"AH\"]}'")
		return shim.Error("CreateUserObject(): Incorrect number of arguments. Expecting 1 ")
	}

	rs, err := GetList(stub, "UserCat", args)
	if err != nil {
		error_str := fmt.Sprintf("GetUserListByCat operation failed. Error marshaling JSON: %s", err)
		return shim.Error(error_str)
	}

	defer rs.Close()

	// Iterate through result set
	var i int
	var tlist []UserObject // Define a list
	for i = 0; rs.HasNext(); i++ {

		// We can process whichever return value is of interest
		responseRange, err := rs.Next()
		if err != nil {
			return shim.Success(nil)
		}
		uo, err := JSONtoUser(responseRange.Value)
		if err != nil {
			error_str := fmt.Sprintf("GetUserListByCat() operation failed - Unmarshall Error. %s", err)
			fmt.Println(error_str)
			return shim.Error(error_str)
		}

		fmt.Println("GetUserListByCat() : my Value : ", uo)
		tlist = append(tlist, uo)
	}

	jsonRows, err := json.Marshal(tlist)
	if err != nil {
		error_str := fmt.Sprintf("GetUserListByCat() operation failed - Unmarshall Error. %s", err)
		fmt.Println(error_str)
		return shim.Error(error_str)
	}

	//fmt.Println("All Users : ", jsonRows)
	return shim.Success(jsonRows)

}

////////////////////////////////////////////////////////////////////////////
// Get The Highest Bid Received so far for an Auction
// in the block-chain
////////////////////////////////////////////////////////////////////////////
func GetLastBid(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	var Avalbytes []byte

	layout := "2006-01-02 15:04:05"
	highestTime, err := time.Parse(layout, layout)

	rs, err := GetList(stub, "Bid", args)
	if err != nil {
		error_str := fmt.Sprintf("GetListOfBids operation failed. Error marshaling JSON: %s", err)
		return shim.Error(error_str)
	}

	defer rs.Close()
	// Iterate through result set

	for i := 0; rs.HasNext(); i++ {

		// We can process whichever return value is of interest
		responseRange, err := rs.Next()
		if err != nil {
			return shim.Success(nil)
		}
		currentBid, err := JSONtoBid(responseRange.Value)
		if err != nil {
			error_str := fmt.Sprintf("GetHighestBid(0 operation failed. %s", err)
			fmt.Println(error_str)
			return shim.Error(error_str)
		}

		bidTime, err := time.Parse(layout, currentBid.BidTime)
		if err != nil {
			error_str := fmt.Sprintf("GetLastBid() Failed : time Conversion error on BidTime %s", err)
			fmt.Println(error_str)
			return shim.Error(error_str)
		}

		if bidTime.Sub(highestTime) > 0 {
			highestTime = bidTime
			Avalbytes = responseRange.Value
		}
		return shim.Success(Avalbytes)
	}
	return shim.Error("GetLastBid() : Failed - No Bids Found")
}

////////////////////////////////////////////////////////////////////////////
// Get The Highest Bid Received so far for an Auction
// in the block-chain
////////////////////////////////////////////////////////////////////////////
func GetNoOfBidsReceived(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	rs, err := GetList(stub, "Bid", args)
	if err != nil {
		error_str := fmt.Sprintf("GetListOfBids operation failed. Error marshaling JSON: %s", err)
		return shim.Error(error_str)
	}

	defer rs.Close()

	// Iterate through result set
	var i int
	for i = 0; rs.HasNext(); i++ {

		// We can process whichever return value is of interest
		_, err := rs.Next()
		if err != nil {
			return shim.Success(nil)
		}
	}
	return shim.Success([]byte(strconv.Itoa(i)))
}

////////////////////////////////////////////////////////////////////////////
// Get the Highest Bid in the List
//
////////////////////////////////////////////////////////////////////////////
func GetHighestBid(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	var Avalbytes []byte
	highestBid := 0
	rs, err := GetList(stub, "Bid", args)
	if err != nil {
		error_str := fmt.Sprintf("GetListOfBids operation failed. Error marshaling JSON: %s", err)
		return shim.Error(error_str)
	}

	defer rs.Close()

	// Iterate through result set
	var i int
	for i = 0; rs.HasNext(); i++ {

		// We can process whichever return value is of interest
		responseRange, err := rs.Next()
		if err != nil {
			return shim.Success(nil)
		}
		currentBid, err := JSONtoBid(responseRange.Value)
		if err != nil {
			error_str := fmt.Sprintf("GetHighestBid(0 operation failed. %s", err)
			fmt.Println(error_str)
			return shim.Error(error_str)
		}

		bidPrice, err := strconv.Atoi(currentBid.BidPrice)
		if err != nil {
			error_str := fmt.Sprintf("GetHighestBid() Int Conversion error on BidPrice! failed. %s", err)
			fmt.Println(error_str)
			return shim.Error(error_str)
		}

		if bidPrice >= highestBid {
			highestBid = bidPrice
			Avalbytes = responseRange.Value

		}
	}

	return shim.Success(Avalbytes)
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Trigger the Auction
// Structure of args auctionReqID, RecType, AucStartDateTime, Duration in Minutes ( 3 = 3 minutes)
// ./peer chaincode invoke -l golang -n mycc -c '{"Function": "OpenAuctionForBids", "Args":["1111", "OPENAUC", "3", "2006-01-02 15:04:05"]}'
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

func OpenAuctionForBids(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	// Fetch Auction Object and check its Status
	Avalbytes, err := QueryObject(stub, "Auction", []string{args[0]})
	if err != nil {
		fmt.Println("OpenAuctionForBids(): Auction Object Retrieval Failed ")
		return shim.Error("OpenAuctionForBids(): Auction Object Retrieval Failed ")
	}

	aucR, err := JSONtoAucReq(Avalbytes)
	if err != nil {
		fmt.Println("OpenAuctionForBids(): Auction Object Unmarshalling Failed ")
		return shim.Error("OpenAuctionForBids(): Auction Object UnMarshalling Failed ")
	}

	if aucR.Status == "CLOSED" {
		fmt.Println("OpenAuctionForBids(): Auction is Closed - Cannot Open for new bids ")
		return shim.Error("OpenAuctionForBids(): is Closed - Cannot Open for new bids Failed ")
	}

	// Calculate Time Now and Duration of Auction

	// Validate arg[1]  is an integer as it represents Duration in Minutes
	aucDuration, err := strconv.Atoi(args[2])
	if err != nil {
		fmt.Println("OpenAuctionForBids(): Auction Duration is an integer that represents minute! OpenAuctionForBids() Failed ")
		return shim.Error("OpenAuctionForBids(): Auction Duration is an integer that represents minute! OpenAuctionForBids() Failed ")
	}

	aucStartDate, err := time.Parse("2006-01-02 15:04:05", args[3])
	aucEndDate := aucStartDate.Add(time.Duration(aucDuration) * time.Minute)

	// We  don't use go routines anymore to time the auction
	//sleepTime := time.Duration(aucDuration * 60 * 1000 * 1000 * 1000)

	//  Update Auction Object
	aucR.OpenDate = aucStartDate.Format("2006-01-02 15:04:05")
	aucR.CloseDate = aucEndDate.Format("2006-01-02 15:04:05")
	aucR.Status = "OPEN"

	response := UpdateAuctionStatus(stub, "Auction", aucR)
	if response.Status != shim.OK {
		fmt.Println("OpenAuctionForBids(): UpdateAuctionStatus() Failed ")
		return shim.Error("OpenAuctionForBids(): UpdateAuctionStatus() Failed ")
	}

	buff := response.Payload

	// Remove the Auction from INIT Bucket and move to OPEN bucket
	// This was designed primarily to help the UI

	keys := []string{"2016", aucR.AuctionID}
	err = DeleteObject(stub, "AucInit", keys)
	if err != nil {
		fmt.Println("OpenAuctionForBids(): DeleteFromLedger() Failed ")
		return shim.Error("OpenAuctionForBids(): DeleteFromLedger() Failed ")
	}

	// Add the Auction to Open Bucket
	err = UpdateObject(stub, "AucOpen", keys, buff)
	if err != nil {
		fmt.Println("OpenAuctionForBids() : write error while inserting record into AucInit\n")
		return shim.Error(err.Error())
	}

	return shim.Success(buff)
}

//////////////////////////////////////////////////////////////////////////
// Close Open Auctions
// 1. Read OpenAucTable
// 2. Compare now with expiry time with now
// 3. If now is > expiry time call CloseAuction
// ./peer chaincode invoke -l golang -n mycc -c '{"Function": "CloseOpenAuctions", "Args": ["2016", "CLAUC", currentDateTime]}'
//////////////////////////////////////////////////////////////////////////

func CloseOpenAuctions(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	response := GetListOfOpenAucs(stub, "AucOpen", []string{"2016"})
	if response.Status != shim.OK {
		error_str := fmt.Sprintf("CloseOpenAuctions() operation failed. Error retrieving values from AucOpen: %s", response.Message)
		fmt.Println(error_str)
		return shim.Error(error_str)
	}

	rows := response.Payload
	tlist := make([]AuctionRequest, len(rows))
	err := json.Unmarshal([]byte(rows), &tlist)
	if err != nil {
		error_str := fmt.Sprintf("CloseOpenAuctions() Unmarshal operation failed. Error retrieving values from AucOpen: %s", response.Message)
		fmt.Println(error_str)
		return shim.Error(error_str)
	}

	for i := 0; i < len(tlist); i++ {
		ar := tlist[i]

		fmt.Println("CloseOpenAuctions() ", ar)

		// Compare Auction Times where args[2] = the CurrentTime sent by the client
		fmt.Println("CloseOpenAuctions() : ", args[2], ": ar.CloseDate : ", ar.CloseDate)
		if tCompare(args[2], ar.CloseDate) == false {

			// Request Closing Auction
			response := CloseAuction(stub, "CloseAuction", []string{ar.AuctionID})
			if response.Status != shim.OK {
				error_str := fmt.Sprintf("CloseOpenAuctions() operation failed. %s", err)
				fmt.Println(error_str)
				return shim.Error(error_str)
			}
		}
	}

	return shim.Success(nil)
}

//////////////////////////////////////////////////////////////////////////
// Close the Auction
// This is invoked by OpenAuctionForBids
// which kicks-off a go-routine timer for the duration of the auction
// When the timer expires, it creates a shell script to CloseAuction() and triggers it
// This function can also be invoked via CLI - the intent was to close as and when I implement BuyItNow()
// CloseAuction
// - Sets the status of the Auction to "CLOSED"
// - Removes the Auction from the Open Auction list (AucOpenTable)
// - Retrieves the Highest Bid and creates a Transaction
// - Posts The Transaction
//
// To invoke from Command Line via CLI or REST API
// ./peer chaincode invoke -l golang -n mycc -c '{"Function": "CloseAuction", "Args": ["1111", "AUCREQ"]}'
// ./peer chaincode invoke -l golang -n mycc -c '{"Function": "CloseAuction", "Args": ["1111", "AUCREQ"]}'
//
//////////////////////////////////////////////////////////////////////////

func CloseAuction(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	// Close The Auction -  Fetch Auction Object
	Avalbytes, err := QueryObject(stub, "Auction", []string{args[0]})
	if err != nil {
		fmt.Println("CloseAuction(): Auction Object Retrieval Failed ")
		return shim.Error("CloseAuction(): Auction Object Retrieval Failed ")
	}

	aucR, err := JSONtoAucReq(Avalbytes)
	if err != nil {
		fmt.Println("CloseAuction(): Auction Object Unmarshalling Failed ")
		return shim.Error("CloseAuction(): Auction Object UnMarshalling Failed ")
	}

	//  Update Auction Status
	aucR.Status = "CLOSED"
	fmt.Println("CloseAuction(): UpdateAuctionStatus() successful ", aucR)

	response := UpdateAuctionStatus(stub, "Auction", aucR)
	if response.Status != shim.OK {
		fmt.Println("CloseAuction(): UpdateAuctionStatus() Failed ")
		return shim.Error("CloseAuction(): UpdateAuctionStatus() Failed ")
	}
	Avalbytes = response.Payload

	// Remove the Auction from Open Bucket
	keys := []string{"2016", aucR.AuctionID}
	err = DeleteObject(stub, "AucOpen", keys)
	if err != nil {
		fmt.Println("CloseAuction(): DeleteFromLedger(AucOpenTable) Failed ")
		return shim.Error("CloseAuction(): DeleteFromLedger(AucOpen) Failed ")
	}

	fmt.Println("CloseAuction(): Proceeding to process the highest bid ")

	// Process Final Bid - Turn it into a Transaction
	response = GetHighestBid(stub, "GetHighestBid", []string{args[0]})
	Avalbytes = response.Payload
	if Avalbytes == nil {
		fmt.Println("CloseAuction(): No bids available, no change in Item Status - PostTransaction() Completed Successfully ")
		return shim.Success(Avalbytes)
	}

	if response.Status != shim.OK {
		fmt.Println("CloseAuction(): No bids available, error encountered - PostTransaction() failed ")
		return shim.Error(err.Error())
	}

	bid, _ := JSONtoBid(Avalbytes)
	fmt.Println("CloseAuction(): Proceeding to process the highest bid ", bid)
	tran := BidtoTransaction(bid)
	fmt.Println("CloseAuction(): Converting Bid to tran ", tran)

	// Process the last bid once Time Expires
	tranArgs := []string{tran.AuctionID, tran.RecType, tran.ItemID, tran.TransType, tran.UserId, tran.TransDate, tran.HammerTime, tran.HammerPrice, tran.Details}
	fmt.Println("CloseAuction(): Proceeding to process the  Transaction ", tranArgs)

	response = PostTransaction(stub, "PostTransaction", tranArgs)
	if response.Status != shim.OK {
		fmt.Println("CloseAuction(): PostTransaction() Failed ")
		return shim.Error("CloseAuction(): PostTransaction() Failed ")
	}
	Avalbytes = response.Payload
	fmt.Println("CloseAuction(): PostTransaction() Completed Successfully ")
	return shim.Success(Avalbytes)

}

////////////////////////////////////////////////////////////////////////////////////////////
// Buy It Now
// Rules:
// If Buy IT Now Option is available then a Buyer has the option to buy the ITEM
// before the bids exceed BuyITNow Price . Normally, The application should take of this
// at the UI level and this chain-code assumes application has validated that
////////////////////////////////////////////////////////////////////////////////////////////

func BuyItNow(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {

	// Process Final Bid - Turn it into a Transaction
	response := GetHighestBid(stub, "GetHighestBid", []string{args[0]})
	bid, err := JSONtoBid(response.Payload)
	if err != nil {
		return shim.Error("BuyItNow() : JSONtoBid Error")
	}

	// Check if BuyItNow Price > Highest Bid so far
	binP, err := strconv.Atoi(args[5])
	if err != nil {
		return shim.Error("BuyItNow() : Invalid BuyItNow Price")
	}

	hbP, err := strconv.Atoi(bid.BidPrice)
	if err != nil {
		return shim.Error("BuyItNow() : Invalid Highest Bid Price")
	}

	if hbP > binP {
		return shim.Error("BuyItNow() : Highest Bid Price > BuyItNow Price - BuyItNow Rejected")
	}

	// Close The Auction -  Fetch Auction Object
	Avalbytes, err := QueryObject(stub, "Auction", []string{args[0]})
	if err != nil {
		fmt.Println("BuyItNow(): Auction Object Retrieval Failed ")
		return shim.Error("BuyItNow(): Auction Object Retrieval Failed ")
	}

	aucR, err := JSONtoAucReq(Avalbytes)
	if err != nil {
		fmt.Println("BuyItNow(): Auction Object Unmarshalling Failed ")
		return shim.Error("BuyItNow(): Auction Object UnMarshalling Failed ")
	}

	//  Update Auction Status
	aucR.Status = "CLOSED"
	fmt.Println("BuyItNow(): UpdateAuctionStatus() successful ", aucR)

	response = UpdateAuctionStatus(stub, "Auction", aucR)
	if response.Status != shim.OK {
		fmt.Println("BuyItNow(): UpdateAuctionStatus() Failed ")
		return shim.Error("BuyItNow(): UpdateAuctionStatus() Failed ")
	}
	Avalbytes = response.Payload

	// Remove the Auction from Open Bucket
	keys := []string{"2016", aucR.AuctionID}
	err = DeleteObject(stub, "AucOpen", keys)
	if err != nil {
		fmt.Println("BuyItNow(): DeleteFromLedger(AucOpen) Failed ")
		return shim.Error("BuyItNow(): DeleteFromLedger(AucOpen) Failed ")
	}

	fmt.Println("BuyItNow(): Proceeding to process the highest bid ")

	// Convert the BuyITNow to a Bid type struct
	buyItNowBid, err := CreateBidObject(args[0:])
	if err != nil {
		return shim.Error(err.Error())
	}

	// Reject the offer if the Buyer Information Is not Valid or not registered on the Block Chain
	response = ValidateMember(stub, args[4])
	if response.Status != shim.OK {
		fmt.Println("BuyItNow() : Failed Buyer not registered on the block-chain ", args[4])
		return shim.Error(err.Error())
	}

	buyerInfo := response.Payload
	fmt.Println("Buyer information  ", buyerInfo, args[4])

	tran := BidtoTransaction(buyItNowBid)
	fmt.Println("BuyItNow(): Converting Bid to tran ", tran)

	// Process the buy-it-now offer
	tranArgs := []string{tran.AuctionID, tran.RecType, tran.ItemID, tran.TransType, tran.UserId, tran.TransDate, tran.HammerTime, tran.HammerPrice, tran.Details}
	fmt.Println("BuyItNow(): Proceeding to process the  Transaction ", tranArgs)

	response = PostTransaction(stub, "PostTransaction", tranArgs)
	if response.Status != shim.OK {
		fmt.Println("BuyItNow(): PostTransaction() Failed ")
		return shim.Error("CloseAuction(): PostTransaction() Failed ")
	}

	fmt.Println("BuyItNow(): PostTransaction() Completed Successfully ")
	return response
}

//////////////////////////////////////////////////////////////////////////
// Update the Auction Object
// This function updates the status of the auction
// from INIT to OPEN to CLOSED
//////////////////////////////////////////////////////////////////////////

func UpdateAuctionStatus(stub shim.ChaincodeStubInterface, tableName string, ar AuctionRequest) pb.Response {

	buff, err := AucReqtoJSON(ar)
	if err != nil {
		fmt.Println("UpdateAuctionStatus() : Failed Cannot create object buffer for write : ", ar.AuctionID)
		return shim.Error("UpdateAuctionStatus(): Failed Cannot create object buffer for write : " + ar.AuctionID)
	}

	// Update the ledger with the Buffer Data
	//keys := []string{ar.AuctionID, ar.ItemID}
	keys := []string{ar.AuctionID}
	err = ReplaceObject(stub, "Auction", keys, buff)
	if err != nil {
		fmt.Println("UpdateAuctionStatus() : write error while inserting record\n")
		return shim.Error(err.Error())
	}
	return shim.Success(buff)
}

/////////////////////////////////////////////////////////////////////////////////////////////
// Return the right Object Buffer after validation to write to the ledger
// var recType = []string{"ARTINV", "USER", "BID", "AUCREQ", "POSTTRAN", "OPENAUC", "CLAUC"}
/////////////////////////////////////////////////////////////////////////////////////////////

func ProcessQueryResult(stub shim.ChaincodeStubInterface, Avalbytes []byte, args []string) error {

	// Identify Record Type by scanning the args for one of the recTypes
	// This is kind of a post-processor once the query fetches the results
	// RecType is the style of programming in the punch card days ..
	// ... well

	var dat map[string]interface{}

	if err := json.Unmarshal(Avalbytes, &dat); err != nil {
		panic(err)
	}

	var recType string
	recType = dat["RecType"].(string)
	switch recType {

	case "ARTINV":

		ar, err := JSONtoAR(Avalbytes) //
		if err != nil {
			fmt.Println("ProcessRequestType(): Cannot create itemObject \n")
			return err
		}
		// Decrypt Image and Save Image in a file
		image := Decrypt(ar.AES_Key, ar.ItemImage)
		if err != nil {
			fmt.Println("ProcessRequestType() : Image decrytion failed ")
			return err
		}
		fmt.Println("ProcessRequestType() : Image conversion from byte[] to file Successful ")
		err = ByteArrayToImage(image, "copy."+ar.ItemPicFN)
		if err != nil {

			fmt.Println("ProcessRequestType() : Image conversion from byte[] to file failed ")
			return err
		}
		return err

	case "USER":
		ur, err := JSONtoUser(Avalbytes) //
		if err != nil {
			return err
		}
		fmt.Println("ProcessRequestType() : ", ur)
		return err

	case "AUCREQ":
		ar, err := JSONtoAucReq(Avalbytes) //
		if err != nil {
			return err
		}
		fmt.Println("ProcessRequestType() : ", ar)
		return err

	case "OPENAUC":
		ar, err := JSONtoAucReq(Avalbytes) //
		if err != nil {
			return err
		}
		fmt.Println("ProcessRequestType() : ", ar)
		return err
	case "CLAUC":
		ar, err := JSONtoAucReq(Avalbytes) //
		if err != nil {
			return err
		}
		fmt.Println("ProcessRequestType() : ", ar)
		return err
	case "POSTTRAN":
		atr, err := JSONtoTran(Avalbytes) //
		if err != nil {
			return err
		}
		fmt.Println("ProcessRequestType() : ", atr)
		return err
	case "BID":
		bid, err := JSONtoBid(Avalbytes) //
		if err != nil {
			return err
		}
		fmt.Println("ProcessRequestType() : ", bid)
		return err
	case "DEFAULT":
		return nil
	case "XFER":
		return nil
	default:
		return errors.New("Unknown")
	}
	return nil

}
